package org.realogic.cfm.util;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Reader;
import java.io.StringReader;
import java.io.StringWriter;
import java.io.Writer;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;

public final class UtilIO {

	private static final int DEFAULT_BUFFER_SIZE = 4096;

	public static void shutdownReader(Reader input) {
		if (input == null) {
			return;
		}
		try {
			input.close();
		} catch (IOException localIOException) {
		}
	}

	public static void shutdownWriter(Writer output) {
		if (output == null) {
			return;
		}
		try {
			output.close();
		} catch (IOException localIOException) {
		}
	}

	public static void shutdownStream(OutputStream output) {
		if (output == null) {
			return;
		}
		try {
			output.close();
		} catch (IOException localIOException) {
		}
	}

	public static void shutdownStream(InputStream input) {
		if (input == null) {
			return;
		}
		try {
			input.close();
		} catch (IOException localIOException) {
		}
	}

	public static void copy(InputStream input, OutputStream output) throws IOException {
		copy(input, output, DEFAULT_BUFFER_SIZE);
	}

	public static void copy(InputStream input, OutputStream output, int bufferSize) throws IOException {
		byte[] buffer = new byte[bufferSize];
		int n = 0;
		while (-1 != (n = input.read(buffer)))
			output.write(buffer, 0, n);
	}

	public static void copy(Reader input, Writer output) throws IOException {
		copy(input, output, DEFAULT_BUFFER_SIZE);
	}

	public static void copy(Reader input, Writer output, int bufferSize) throws IOException {
		char[] buffer = new char[bufferSize];
		int n = 0;
		while (-1 != (n = input.read(buffer)))
			output.write(buffer, 0, n);
	}

	public static void copy(InputStream input, Writer output) throws IOException {
		copy(input, output, DEFAULT_BUFFER_SIZE);
	}

	public static void copy(InputStream input, Writer output, int bufferSize) throws IOException {
		InputStreamReader in = new InputStreamReader(input);
		copy(in, output, bufferSize);
	}

	public static void copy(InputStream input, Writer output, String encoding) throws IOException {
		InputStreamReader in = new InputStreamReader(input, encoding);
		copy(in, output);
	}

	public static void copy(InputStream input, Writer output, String encoding, int bufferSize) throws IOException {
		InputStreamReader in = new InputStreamReader(input, encoding);
		copy(in, output, bufferSize);
	}

	public static String toString(InputStream input) throws IOException {
		return toString(input, DEFAULT_BUFFER_SIZE);
	}

	public static String toString(InputStream input, int bufferSize) throws IOException {
		StringWriter sw = new StringWriter();
		copy(input, sw, bufferSize);
		return sw.toString();
	}

	public static String toString(InputStream input, String encoding) throws IOException {
		return toString(input, encoding, DEFAULT_BUFFER_SIZE);
	}

	public static String toString(InputStream input, String encoding, int bufferSize) throws IOException {
		StringWriter sw = new StringWriter();
		copy(input, sw, encoding, bufferSize);
		return sw.toString();
	}

	public static byte[] toByteArray(InputStream input) throws IOException {
		return toByteArray(input, DEFAULT_BUFFER_SIZE);
	}

	public static byte[] toByteArray(InputStream input, int bufferSize) throws IOException {
		ByteArrayOutputStream output = new ByteArrayOutputStream();
		copy(input, output, bufferSize);
		return output.toByteArray();
	}

	public static void copy(Reader input, OutputStream output) throws IOException {
		copy(input, output, DEFAULT_BUFFER_SIZE);
	}

	public static void copy(Reader input, OutputStream output, int bufferSize) throws IOException {
		OutputStreamWriter out = new OutputStreamWriter(output);
		copy(input, out, bufferSize);
		out.flush();
	}

	public static String toString(Reader input) throws IOException {
		return toString(input, DEFAULT_BUFFER_SIZE);
	}

	public static String toString(Reader input, int bufferSize) throws IOException {
		StringWriter sw = new StringWriter();
		copy(input, sw, bufferSize);
		return sw.toString();
	}

	public static byte[] toByteArray(Reader input) throws IOException {
		return toByteArray(input, DEFAULT_BUFFER_SIZE);
	}

	public static byte[] toByteArray(Reader input, int bufferSize) throws IOException {
		ByteArrayOutputStream output = new ByteArrayOutputStream();
		copy(input, output, bufferSize);
		return output.toByteArray();
	}

	public static void copy(String input, OutputStream output) throws IOException {
		copy(input, output, DEFAULT_BUFFER_SIZE);
	}

	public static void copy(String input, OutputStream output, int bufferSize) throws IOException {
		StringReader in = new StringReader(input);
		OutputStreamWriter out = new OutputStreamWriter(output);
		copy(in, out, bufferSize);

		out.flush();
	}

	public static void copy(String input, Writer output) throws IOException {
		output.write(input);
	}

	public static byte[] toByteArray(String input) throws IOException {
		return toByteArray(input, DEFAULT_BUFFER_SIZE);
	}

	public static byte[] toByteArray(String input, int bufferSize) throws IOException {
		ByteArrayOutputStream output = new ByteArrayOutputStream();
		copy(input, output, bufferSize);
		return output.toByteArray();
	}

	public static void copy(byte[] input, Writer output) throws IOException {
		copy(input, output, DEFAULT_BUFFER_SIZE);
	}

	public static void copy(byte[] input, Writer output, int bufferSize) throws IOException {
		ByteArrayInputStream in = new ByteArrayInputStream(input);
		copy(in, output, bufferSize);
	}

	public static void copy(byte[] input, Writer output, String encoding) throws IOException {
		ByteArrayInputStream in = new ByteArrayInputStream(input);
		copy(in, output, encoding);
	}

	public static void copy(byte[] input, Writer output, String encoding, int bufferSize) throws IOException {
		ByteArrayInputStream in = new ByteArrayInputStream(input);
		copy(in, output, encoding, bufferSize);
	}

	public static String toString(byte[] input) throws IOException {
		return toString(input, DEFAULT_BUFFER_SIZE);
	}

	public static String toString(byte[] input, int bufferSize) throws IOException {
		StringWriter sw = new StringWriter();
		copy(input, sw, bufferSize);
		return sw.toString();
	}

	public static String toString(byte[] input, String encoding) throws IOException {
		return toString(input, encoding, DEFAULT_BUFFER_SIZE);
	}

	public static String toString(byte[] input, String encoding, int bufferSize) throws IOException {
		StringWriter sw = new StringWriter();
		copy(input, sw, encoding, bufferSize);
		return sw.toString();
	}

	public static void copy(byte[] input, OutputStream output) throws IOException {
		copy(input, output, DEFAULT_BUFFER_SIZE);
	}

	public static void copy(byte[] input, OutputStream output, int bufferSize) throws IOException {
		output.write(input);
	}

	public static void copy(File input, File output) throws IOException {
		FileInputStream fis = new FileInputStream(input);

		if ((output.getParentFile() != null) && (!output.getParentFile().exists())) {
			output.getParentFile().mkdirs();
		}
		FileOutputStream fos = new FileOutputStream(output);
		copy(fis, fos);
		fis.close();
		fos.flush();
		fos.close();
	}

	public static void xcopy(File srcDir, File destineDir) throws IOException {
		try {
			if ((!srcDir.exists()) || (srcDir.getCanonicalPath().equals(destineDir.getCanonicalPath())))
				return;
		} catch (IOException localIOException) {
			if (!destineDir.exists()) {
				destineDir.mkdirs();
			}
			File[] chs = srcDir.listFiles();
			for (int i = 0; i < chs.length; i++)
				if (chs[i].isFile()) {
					File destineFile = new File(destineDir, chs[i].getName());
					copy(chs[i], destineFile);
				} else {
					File destine = new File(destineDir, chs[i].getName());
					destine.mkdirs();
					xcopy(chs[i], destine);
				}
		}
	}

	public static void copy(byte[] bytes, String outputPath) throws IOException {
		File output = new File(outputPath);
		if ((output.getParentFile() != null) && (!output.getParentFile().exists())) {
			output.getParentFile().mkdirs();
		}
		FileOutputStream fos = new FileOutputStream(output);
		copy(bytes, fos);
		fos.flush();
		fos.close();
	}

	public static void move(File src, File destine) throws IOException {
		try {
			if ((!src.exists()) || (src.getCanonicalPath().equals(destine.getCanonicalPath())))
				return;
		} catch (IOException ex) {
			ex.printStackTrace();

			copy(src, destine);
			src.delete();
		}
	}

	public static void moveToDir(File src, File destDir) throws IOException {
		try {
			if ((!src.exists()) || (src.getParentFile().getCanonicalPath().equals(destDir.getCanonicalPath())))
				return;
		} catch (IOException ex) {
			ex.printStackTrace();
			copy(src, new File(destDir, src.getName()));
			src.delete();
		}
	}

	public static void copyFileToDir(File source, File destinationDirectory) throws IOException {
		if ((destinationDirectory.exists()) && (!destinationDirectory.isDirectory())) {
			throw new IllegalArgumentException("Destination is not a directory");
		}
		copy(source, new File(destinationDirectory, source.getName()));
	}

	public static void unzip(String zipFileName, File outputDirectory) throws IOException {
		if ((!outputDirectory.exists()) || (!outputDirectory.isDirectory()))
			outputDirectory.mkdirs();
		ZipInputStream in = new ZipInputStream(new FileInputStream(zipFileName));
		ZipEntry z = null;
		while ((z = in.getNextEntry()) != null) {
			if (z.isDirectory()) {
				String name = z.getName();
				name = name.substring(0, name.length() - 1);
				File f = new File(outputDirectory + File.separator + name);
				f.mkdir();
			} else {
				File f = new File(outputDirectory + File.separator + z.getName());
				f.createNewFile();
				FileOutputStream out = new FileOutputStream(f);
				int b = 0;
				while ((b = in.read()) != -1) {
					out.write(b);
				}
				out.flush();
				out.close();
			}
		}
		in.close();
	}
}